feat(ios): Default to consuming sentry-cocoa as an xcframework#6381
Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
🤖 This preview updates automatically when you update the PR. |
|
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c8143aa. Configure here.
|
It would probably be nice to include it to the next release but no stress |
📲 Install BuildsAndroid
|
Android (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 414.88 ms | 428.68 ms | 13.81 ms |
| a736b76+dirty | 405.78 ms | 458.74 ms | 52.96 ms |
| 5569641+dirty | 465.92 ms | 532.22 ms | 66.30 ms |
| 580fb5c+dirty | 515.72 ms | 585.38 ms | 69.66 ms |
| 7ff4d0f+dirty | 403.38 ms | 427.06 ms | 23.68 ms |
| 6177334+dirty | 404.80 ms | 456.74 ms | 51.94 ms |
| 1e5d96d+dirty | 423.33 ms | 482.46 ms | 59.13 ms |
| f170ec3+dirty | 505.96 ms | 551.88 ms | 45.92 ms |
| 20fbd51+dirty | 594.38 ms | 655.35 ms | 60.97 ms |
| f3215d3+dirty | 396.53 ms | 436.66 ms | 40.13 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 43.94 MiB | 48.99 MiB | 5.05 MiB |
| a736b76+dirty | 48.30 MiB | 53.48 MiB | 5.18 MiB |
| 5569641+dirty | 48.30 MiB | 53.48 MiB | 5.18 MiB |
| 580fb5c+dirty | 49.74 MiB | 54.79 MiB | 5.05 MiB |
| 7ff4d0f+dirty | 48.30 MiB | 53.60 MiB | 5.30 MiB |
| 6177334+dirty | 48.30 MiB | 53.54 MiB | 5.23 MiB |
| 1e5d96d+dirty | 49.74 MiB | 54.81 MiB | 5.07 MiB |
| f170ec3+dirty | 48.30 MiB | 53.57 MiB | 5.26 MiB |
| 20fbd51+dirty | 49.74 MiB | 54.81 MiB | 5.07 MiB |
| f3215d3+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
Android (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 403.57 ms | 437.00 ms | 33.43 ms |
| 64630e5+dirty | 419.18 ms | 464.58 ms | 45.40 ms |
| 853723c+dirty | 405.54 ms | 440.08 ms | 34.54 ms |
| 1122a96+dirty | 422.22 ms | 464.33 ms | 42.10 ms |
| 5748023+dirty | 446.69 ms | 505.63 ms | 58.94 ms |
| eb93136+dirty | 416.18 ms | 467.32 ms | 51.14 ms |
| 4e0ba9c+dirty | 452.84 ms | 473.36 ms | 20.52 ms |
| c2e182c+dirty | 471.64 ms | 553.59 ms | 81.95 ms |
| a0d8cf8+dirty | 411.71 ms | 467.57 ms | 55.87 ms |
| d0e3b3e+dirty | 421.53 ms | 498.19 ms | 76.66 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 0d9949d+dirty | 43.75 MiB | 48.13 MiB | 4.37 MiB |
| 64630e5+dirty | 49.74 MiB | 54.82 MiB | 5.07 MiB |
| 853723c+dirty | 48.30 MiB | 53.58 MiB | 5.28 MiB |
| 1122a96+dirty | 48.30 MiB | 53.54 MiB | 5.24 MiB |
| 5748023+dirty | 48.30 MiB | 53.54 MiB | 5.23 MiB |
| eb93136+dirty | 48.30 MiB | 53.58 MiB | 5.28 MiB |
| 4e0ba9c+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
| c2e182c+dirty | 49.74 MiB | 54.85 MiB | 5.11 MiB |
| a0d8cf8+dirty | 48.30 MiB | 53.49 MiB | 5.19 MiB |
| d0e3b3e+dirty | 49.74 MiB | 55.09 MiB | 5.34 MiB |
antonis
left a comment
There was a problem hiding this comment.
Since the dynamic approach didn't resolve the CI build issue and this partially a breaking change for the users I suggest to try the following:
- Keep SPM opt-in till the React Native framework supports it
- Have RNSentry.podspec consume sentry-cocoa as a vendored_frameworks xcframework downloaded from sentry-cocoa's GitHub releases, instead of either s.dependency 'Sentry' (CocoaPods trunk) or SPM.dependency (spm.rb bridge).
Wdyt?
iOS (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 3842.29 ms | 1212.12 ms | -2630.17 ms |
| 0bd8916+dirty | 3842.33 ms | 1230.76 ms | -2611.58 ms |
| 774257e+dirty | 3846.90 ms | 1215.02 ms | -2631.88 ms |
| acd838e+dirty | 3849.78 ms | 1230.00 ms | -2619.78 ms |
| 038a6d7+dirty | 3849.69 ms | 1228.40 ms | -2621.28 ms |
| df5d108+dirty | 1225.90 ms | 1220.14 ms | -5.76 ms |
| 2c735cc+dirty | 1229.67 ms | 1221.50 ms | -8.17 ms |
| 5a010b7+dirty | 3838.85 ms | 1214.98 ms | -2623.87 ms |
| f170ec3+dirty | 3822.26 ms | 1218.33 ms | -2603.93 ms |
| 4953e94+dirty | 1212.06 ms | 1214.83 ms | 2.77 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 4.98 MiB | 6.50 MiB | 1.52 MiB |
| 0bd8916+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 774257e+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| acd838e+dirty | 5.15 MiB | 6.70 MiB | 1.55 MiB |
| 038a6d7+dirty | 5.15 MiB | 6.70 MiB | 1.55 MiB |
| df5d108+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 2c735cc+dirty | 3.38 MiB | 4.74 MiB | 1.35 MiB |
| 5a010b7+dirty | 5.15 MiB | 6.69 MiB | 1.54 MiB |
| f170ec3+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 4953e94+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
iOS (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 3842.23 ms | 1210.00 ms | -2632.23 ms |
| 41d6254+dirty | 3849.78 ms | 1233.91 ms | -2615.86 ms |
| 7d8c8bd+dirty | 3847.98 ms | 1230.77 ms | -2617.21 ms |
| c823bb5+dirty | 3845.16 ms | 1210.33 ms | -2634.83 ms |
| bc0d8cf+dirty | 3834.64 ms | 1223.91 ms | -2610.73 ms |
| 1e5d96d+dirty | 3845.93 ms | 1222.51 ms | -2623.42 ms |
| 7d6fd3a+dirty | 1210.89 ms | 1217.63 ms | 6.74 ms |
| 7436d0f+dirty | 3861.51 ms | 1231.07 ms | -2630.44 ms |
| 4953e94+dirty | 1217.41 ms | 1223.53 ms | 6.12 ms |
| 6acdf1d+dirty | 3835.35 ms | 1218.30 ms | -2617.06 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 57e0069+dirty | 4.98 MiB | 6.50 MiB | 1.52 MiB |
| 41d6254+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| 7d8c8bd+dirty | 5.15 MiB | 6.68 MiB | 1.53 MiB |
| c823bb5+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| bc0d8cf+dirty | 5.15 MiB | 6.67 MiB | 1.51 MiB |
| 1e5d96d+dirty | 4.98 MiB | 6.46 MiB | 1.49 MiB |
| 7d6fd3a+dirty | 3.38 MiB | 4.77 MiB | 1.39 MiB |
| 7436d0f+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| 4953e94+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 6acdf1d+dirty | 4.98 MiB | 6.51 MiB | 1.53 MiB |
Consuming sentry-cocoa through Xcode's SPM integration triggers a signature-copy collision during `xcodebuild archive` on Xcode 16/26: xcodebuild: error: "Sentry-Dynamic.xcframework-ios.signature" couldn't be copied to "Signatures" because an item with the same name already exists.: File exists The collision is specific to Xcode's SPM archive pipeline. Consuming the same prebuilt xcframework through CocoaPods' `vendored_frameworks` avoids that pipeline entirely — the archive step goes through the regular CocoaPods embed path, which does not produce the duplicate signature copy. RNSentry.podspec now downloads `Sentry-Dynamic.xcframework.zip` from sentry-cocoa's GitHub release on first `pod install`, verifies the SHA256 checksum against a version-pinned table in `sentry_utils.rb`, and vendors the extracted xcframework via `s.vendored_frameworks`. Subsequent `pod install` runs reuse the cached copy under `packages/core/ios/Vendor/`. Set `SENTRY_USE_XCFRAMEWORK=0` to fall back to the source-built `Sentry` CocoaPod (e.g. for offline builds behind a restrictive proxy). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…odule Sentry-Dynamic.xcframework contains a framework named `Sentry.framework` inside, so `@import Sentry;` needs `-framework Sentry`. CocoaPods derives the `-framework` flag from the xcframework's own filename, so with `Sentry-Dynamic.xcframework` it generates `-framework Sentry-Dynamic` and RNSentry fails to compile with `Module 'Sentry' not found`. Switch to `Sentry.xcframework` (the static product) — enclosing name matches the framework name inside, so CocoaPods generates the correct `-framework Sentry` and the module resolves. Static also means no embed step, so no chance of the archive-signature collision either. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Sentinel-check `Sentry.xcframework/Info.plist` instead of directory existence so an interrupted `unzip` doesn't leave a partial tree that short-circuits future re-downloads (cursor-bot low). - `rm_rf(target_dir)` before extracting so a stale partial tree from an earlier failure doesn't survive the next attempt. - Verify `Info.plist` after extraction so a release with a changed archive layout fails fast with a clear message instead of silently succeeding and later confusing `pod install` (sentry-bot medium). - Honor `SENTRY_USE_SPM=0` as a deprecated alias for the CocoaPods fallback so CI/local envs still exporting the old draft variable don't silently opt into the new xcframework path (cursor-bot medium). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ramework Even with `s.vendored_frameworks = 'ios/Vendor/Sentry.xcframework'`, CocoaPods didn't propagate a framework search path into RNSentry's own compile phase, so `#import <Sentry/SentryDefines.h>` failed with "file not found". Set `FRAMEWORK_SEARCH_PATHS` explicitly via `pod_target_xcconfig` so the pod can resolve the `Sentry` framework module from the vendored xcframework's parent directory. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`s.pod_target_xcconfig` is setter-only in the CocoaPods version used by RN 0.86, so calling `s.pod_target_xcconfig.merge!(…)` crashed pod install with `undefined method 'pod_target_xcconfig' for Pod::Specification`. Accumulate the settings into a local hash across the conditional branches and assign to `s.pod_target_xcconfig` once at the end. Same fix applied to the pre-existing new-arch/RN<0.71 branch (which had the same latent bug). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Assigning `s.pod_target_xcconfig` at the end of the podspec (after `install_modules_dependencies`) clobbered every setting RN's helper had written, so the RN-provided HEADER_SEARCH_PATHS were dropped and every `#import <Sentry/…>` (as well as any other framework header lookup) failed during RNSentry's compile phase. Assign the base `pod_target_xcconfig` (with DEFINES_MODULE and the Sentry FRAMEWORK_SEARCH_PATHS) BEFORE `install_modules_dependencies` so it merges its RN settings on top rather than the other way around. For the RN < 0.71 branch — where `install_modules_dependencies` doesn't exist — the local hash is mutated after that assignment, so re-assign inside that branch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…H_PATHS Confirmed by local repro: Xcode's `-F <dir>` does NOT descend into an `.xcframework` bundle at search-path lookup time. Given `FRAMEWORK_SEARCH_PATHS = ".../ios/Vendor"`, Xcode only sees `Sentry.xcframework` as an opaque directory and never finds `Sentry.framework` inside — so `#import <Sentry/SentryDefines.h>` fails with `Module 'Sentry' not found`. Instead of a single parent-of-xcframework path, enumerate every slice directory inside the extracted xcframework (via `Dir.children` — no plist gem needed) and register each as a framework search path. Xcode then picks the matching slice based on the target platform/arch. The list is computed at pod-install time, so future sentry-cocoa releases can add new slices without a code change. Apply the same paths to `s.user_target_xcconfig` so the host app target (any user code writing `#import <Sentry/…>` directly) also resolves the module. Verified locally: RNSentry pod and the sample app both compile — only the RN bundle script (unrelated to Sentry) blocks the local build. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two problems with the previous flat-slice-list approach: 1. Xcode's Swift module precompiler walked slices that don't match the current build target (e.g. watchos-* on an iOS build) and errored with 'unsupported Swift architecture'. Fix: split slices by target SDK and emit conditional FRAMEWORK_SEARCH_PATHS[sdk=...*] entries so each SDK build only sees the slices it can actually consume. 2. PODS_TARGET_SRCROOT is defined in a pod's own xcconfig but not in the aggregate/user-target xcconfig. Using it in user_target_xcconfig made the app-target search paths resolve to nothing, so app code writing @import Sentry failed with 'Module Sentry not found'. Use PODS_ROOT/../.. for the user-target xcconfig - from the app's Pods dir that's the RN app root where node_modules/@sentry/react-native/ lives. Slice-to-SDK mapping is computed at pod-install time from the extracted xcframework so future sentry-cocoa releases pick up new slices automatically. Verified locally: sample's SentryNativeInitializer.m now resolves @import Sentry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two follow-up fixes for the vendored xcframework path:
1. RNSentryCocoaTester (in packages/core/RNSentryCocoaTester/) had its
test target fail with 'Sentry/Sentry.h' file not found because its
Podfile layout is different from the RN sample apps — the previous
${PODS_ROOT}/../.. path assumed a RN app root with node_modules,
which doesn't apply here. Switch user_target_xcconfig to the
absolute path known at pod-install time (via File.expand_path on
the podspec dir). Absolute paths are baked into Pods xcconfigs on
every install, so shareability across machines isn't a concern —
Pods/ is regenerated per install anyway. This also removes the need
for a separate 'pod_target' vs 'user_target' path.
2. Build RN 0.86.0 legacy hermes ios production dynamic (use_frameworks!
:linkage => :dynamic mode) failed with:
Undefined symbols: __swift_FORCE_LOAD_$_swiftCompatibility56
Sentry.xcframework contains Swift code, but RNSentry.podspec's
source_files was Objective-C++ only, so Xcode never auto-linked
the Swift runtime compatibility libraries required by the static
Swift symbols embedded in Sentry.xcframework. Add an empty
RNSentrySwiftLinkStub.swift and include `.swift` in source_files
glob so Xcode treats RNSentry as Swift-consuming and pulls in the
compat libs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adding a Swift file to RNSentry.podspec's source_files (to force Xcode to link Swift runtime compat libs when consuming Sentry.xcframework) made CocoaPods treat RNSentry as a 'Swift pod'. On RN < 0.75, React-hermes doesn't define modular headers, so pod install fails: The Swift pod `RNSentry` depends upon `React-hermes`, which does not define modules. The Swift compat lib linkage is only needed when linking Sentry.xcframework's static Swift symbols into a dynamic framework (use_frameworks! :dynamic), which is a RN 0.86+ scenario anyway. Gate the .swift file on RN >= 0.75 to preserve pod install on the older matrix cells. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Move the SPM/xcframework entry out of the already-released `## 8.17.0` section into a new `## Unreleased` section (danger check). The merge from main pulled 8.17.0's release notes on top and swept the entry inside them. - Add a private constant to RNSentrySwiftLinkStub.swift. A pure-comment Swift file compiles to nothing, which would defeat the whole reason for the stub (forcing Xcode to link Swift runtime compatibility libs when consuming Sentry.xcframework's static Swift symbols). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- sentry_utils.rb: replace system('curl',…) with URI.open from stdlib
open-uri. Same net behavior, no shell escaping to worry about, pure Ruby.
- sentry_utils.rb + RNSentry.podspec: drop the runtime slice-enumeration
helpers. Sentry.xcframework's layout has been stable across releases,
so hardcode the slice → SDK map into a frozen constant
(SENTRY_XCFRAMEWORK_SLICES_BY_SDK) and iterate it directly in the
podspec. Less code, no filesystem scan on every pod install. If
sentry-cocoa ever ships a new platform slice, add a line to the
constant.
- scripts/update-cocoa.sh: extend set-version to also refresh the
Sentry.xcframework.zip SHA256 checksum in sentry_utils.rb. Before
this, bumping sentry-cocoa required editing the checksum by hand — a
silent recipe for typos that would break every user's pod install
with a checksum-mismatch error. Now the script downloads the new
archive, computes SHA256, and rewrites both the version key and the
Sentry value in place with a sanity-check.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Repro on a bare RN app installed via `pnpm install
--config.node-linker=isolated` (pnpm's strict store makes package
directories read-only): pod install failed with
Permission denied @ dir_s_mkdir - .../node_modules/.pnpm/
@sentry+react-native.../ios/Vendor
Under pnpm's isolated store (and Yarn PnP), the SDK package directory
is either a read-only symlink into a shared store or not materialized
on disk at all — writing our xcframework cache there is not portable.
Move the cache to `~/Library/Caches/sentry-react-native/xcframeworks/
<version>/` (macOS user cache, always writable, deduped across
projects on the same machine). Override with `SENTRY_XCFRAMEWORK_CACHE_DIR`
for CI or enterprise setups.
Also drop `s.vendored_frameworks = 'ios/Vendor/Sentry.xcframework'`.
It was decorative — CocoaPods doesn't stage vendored xcframeworks for
`path:` (development) pods, which is why we already had to wire
FRAMEWORK_SEARCH_PATHS manually. Linking still happens: clang's
`-fmodules-autolink` (default) emits the `-framework Sentry`
directive as soon as `@import Sentry;` in RNSentry.mm resolves the
module through the search paths. With the vendored_frameworks entry
gone, the podspec no longer points at a path that only existed inside
node_modules.
Verified locally against a bare RN 0.86 sample installed via pnpm
strict + chmod a-w on the package's ios/ directory: pod install
succeeds, build succeeds, app boots, native crash → dSYM upload path
still works.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
aae21ec to
3eed101
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3eed101. Configure here.
| # `Info.plist` most likely came from an interrupted `unzip` and would | ||
| # otherwise silently short-circuit re-download here. | ||
| target_manifest = File.join(target_dir, 'Info.plist') | ||
| return target_dir if File.file?(target_manifest) |
There was a problem hiding this comment.
Cached xcframework skips checksum
Medium Severity
When Info.plist already exists under the versioned cache directory, ensure_sentry_xcframework returns immediately and never re-checks the zip SHA256 from SENTRY_COCOA_XCFRAMEWORK_CHECKSUMS. Upgrading @sentry/react-native after a checksum fix for the same sentry-cocoa version can leave a stale or tampered binary in use.
Reviewed by Cursor Bugbot for commit 3eed101. Configure here.
pod install now downloads Sentry.xcframework.zip from sentry-cocoa's GitHub release (SHA256-verified) and caches it under ~/Library/Caches/sentry-react-native/xcframeworks/<version>/, instead of building Sentry from source as a CocoaPod. Sentry symbols are then statically linked into the app binary (no framework embed, no dylib dep) via `FRAMEWORK_SEARCH_PATHS[sdk=…*]` + clang's -fmodules-autolink. Motivation: - CocoaPods trunk is winding down; we needed a path off it that also sidesteps the Xcode 16/26 archive bug that hits any signed SPM binary xcframework (`Signatures/*.signature` collision). - Consuming via CocoaPods' `vendored_frameworks` pipeline goes through a different code path and is unaffected. Fallback: set `SENTRY_USE_XCFRAMEWORK=0` before pod install to restore the source-built `Sentry` CocoaPod (for offline builds behind a restrictive proxy, or projects with another pod that transitively depends on the Sentry CocoaPod). Cache location is user-writable (not inside node_modules), which means pnpm's isolated store and Yarn PnP work without changes. Override the cache root with `SENTRY_XCFRAMEWORK_CACHE_DIR`. Verified end-to-end against alpha.3 on: - Real device signed archive (Apple accepts, codesign strict-verify passes) - Native crash → dSYM upload → Sentry frames symbolicated - RN 0.71 archive (via SKIP_BUNDLING) with 21k Sentry symbols in dSYM - EAS Build with npm, pnpm-isolated, and `SENTRY_USE_XCFRAMEWORK=0` - Second EAS build after version bump (no stale-cache pollution) Reapplies the content of PR #6381 (merged prematurely as part of the alpha.3 release, then rolled back via #6412) with the pnpm cache-location fix baked in from the start this time. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…6413) pod install now downloads Sentry.xcframework.zip from sentry-cocoa's GitHub release (SHA256-verified) and caches it under ~/Library/Caches/sentry-react-native/xcframeworks/<version>/, instead of building Sentry from source as a CocoaPod. Sentry symbols are then statically linked into the app binary (no framework embed, no dylib dep) via `FRAMEWORK_SEARCH_PATHS[sdk=…*]` + clang's -fmodules-autolink. Motivation: - CocoaPods trunk is winding down; we needed a path off it that also sidesteps the Xcode 16/26 archive bug that hits any signed SPM binary xcframework (`Signatures/*.signature` collision). - Consuming via CocoaPods' `vendored_frameworks` pipeline goes through a different code path and is unaffected. Fallback: set `SENTRY_USE_XCFRAMEWORK=0` before pod install to restore the source-built `Sentry` CocoaPod (for offline builds behind a restrictive proxy, or projects with another pod that transitively depends on the Sentry CocoaPod). Cache location is user-writable (not inside node_modules), which means pnpm's isolated store and Yarn PnP work without changes. Override the cache root with `SENTRY_XCFRAMEWORK_CACHE_DIR`. Verified end-to-end against alpha.3 on: - Real device signed archive (Apple accepts, codesign strict-verify passes) - Native crash → dSYM upload → Sentry frames symbolicated - RN 0.71 archive (via SKIP_BUNDLING) with 21k Sentry symbols in dSYM - EAS Build with npm, pnpm-isolated, and `SENTRY_USE_XCFRAMEWORK=0` - Second EAS build after version bump (no stale-cache pollution) Reapplies the content of PR #6381 (merged prematurely as part of the alpha.3 release, then rolled back via #6412) with the pnpm cache-location fix baked in from the start this time. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>


📢 Type of change
📜 Description
Vendor
sentry-cocoaas a prebuiltSentry-Dynamic.xcframework(downloaded from the GitHub release and SHA256-verified atpod installtime), instead of buildingSentryfrom source as a CocoaPod. Sidesteps the Xcode 16/26 archive bug that hits when the same xcframework is consumed through Xcode's SPM integration ("Sentry-Dynamic.xcframework-ios.signature" couldn't be copied to "Signatures"…).Override with:
SENTRY_USE_XCFRAMEWORK=0— fall back to the source-builtSentryCocoaPod (e.g. offline builds behind a restrictive proxy).💡 Motivation and Context
CocoaPods source builds of
sentry-cocoaare slow and diverge from where the RN community is moving (prebuilt binaries). SPM was the first attempt, but Xcode 16/26 archives fail with a duplicate-signature error on any signed SPM binary xcframework. Consuming the same xcframework through CocoaPods'vendored_frameworksavoids the Xcode-SPM archive pipeline and works on the full RN version range.💚 How did you test it?
CI: sample-application (iOS matrix, both
xcframeworkdefault andcocoapodsfallback), iOS Size Analysis (archive), metrics (fastlane archive).📝 Checklist
sendDefaultPIIis enabled🔮 Next steps